package com.yds.developtools.utils

import android.os.Environment
import android.util.Log
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStreamWriter

/**
 * 作者:     YDS
 * 创建时间: 2025/9/4 17:00
 * 页面描述: SD卡帮助类
 */
@Suppress("unused")
object YDSDCardHelper {

    /**
     * 检查SD卡是否可用
     * @return 是否可用
     */
    @JvmStatic
    fun isSDCardAvailable(): Boolean {
        return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
    }

    /**
     * 创建文件夹
     * @param folder 要创建的文件夹
     * @return 创建是否成功
     */
    @JvmStatic
    fun createFolder(folder: File): Boolean {
        return if (folder.exists()) {
            true
        } else {
            folder.mkdirs()
        }
    }

    /**
     * 查找指定文件夹下的所有文件，递归遍历子文件夹
     * @param folder 要查找的文件夹
     * @param autoCreate 如果文件夹不存在，是否自动创建
     * @return 文件夹下所有文件的列表，若文件夹不存在且未自动创建则返回空列表
     */
    @JvmStatic
    fun queryFolderOutputFiles(folder: File, autoCreate: Boolean = true): List<File> {
        val fileList = mutableListOf<File>()
        if (!folder.exists()) {// 如果文件夹不存在
            if (autoCreate) {// 如果允许自动创建文件夹
                createFolder(folder)
            }
            // 不管是创建成功或失败，亦或不自动创建文件夹都返回空数组。
            return fileList
        }

        // 检查当前输入文件是否是文件夹
        if (!folder.isDirectory) {
            return fileList
        }

        // 获取文件夹下的所有子文件和文件夹
        val files = folder.listFiles()
        if (files.isNullOrEmpty()) {
            return fileList
        }
        files.forEach { file: File ->
            if (file.isDirectory) {// 如果是文件夹继续遍历
                fileList.addAll(queryFolderOutputFiles(file, autoCreate))
            } else {// 如果是文件直接添加
                fileList.add(file)
            }
        }

        return fileList
    }

    /**
     * 递归删除指定文件夹下的所有文件和子文件夹，包括文件夹本身
     * @param folder 要删除的文件夹
     * @return 是否删除成功
     */
    @JvmStatic
    fun deleteFolder(folder: File): Boolean {
        if (!folder.exists()) {// 文件夹不存在直接返回成功
            return false
        }

        if (folder.isFile) {// 如果是文件，直接删除
            return folder.delete()
        }

        // 递归删除所有子文件和子文件夹
        val files = folder.listFiles()
        files?.forEach {
            // 递归删除子项，若有任何一项删除失败则整体返回失败
            if (!deleteFolder(it)) {
                return false
            }
        }

        // 最后删除空文件夹本身
        return folder.delete()
    }

    /**
     * 只删除指定文件夹下的内容，但保留文件夹本身
     * @param folder 要清空的文件夹
     * @return 是否清空成功
     */
    @JvmStatic
    fun clearFolder(folder: File): Boolean {
        if (!folder.exists() || !folder.isDirectory) {
            return false
        }

        // 递归删除所有子文件和子文件夹
        val files = folder.listFiles()
        files?.forEach {
            // 递归删除子项，若有任何一项删除失败则整体返回失败
            if (!deleteFolder(it)) {
                return false
            }
        }

        return true
    }

    /**
     * 重命名文件或文件夹
     * @param sourceFile 原始文件/文件夹
     * @param newName 新的名称（仅名称，不包含路径）
     * @return 重命名是否成功
     */
    @JvmStatic
    fun renameFileOrFolder(sourceFile: File, newName: String): Boolean {
        // 检查原始文件是否存在
        if (!sourceFile.exists()) {
            return false
        }

        // 检查新名称是否有效
        if (newName.isBlank()) {
            return false
        }

        // 如果名称相同，无需修改
        if (sourceFile.name == newName) {
            return true
        }

        // 创建目标文件对象
        val parentDir = sourceFile.parentFile
        if (parentDir == null || !parentDir.exists()) {
            return false
        }

        val targetFile = File(parentDir, newName)
        // 检查目标文件是否已存在
        if (targetFile.exists()) {
            return false
        }

        // 执行重命名操作
        return try {
            sourceFile.renameTo(targetFile)
        } catch (e: SecurityException) {
            Log.e("YDSimon", "执行重命名操作-SecurityException: ${e.message}")
            false
        } catch (e: Exception) {
            Log.e("YDSimon", "执行重命名操作-Exception: ${e.message}")
            false
        }
    }

    /**
     * 复制单个文件到目标文件夹
     * @param sourceFile 源文件
     * @param targetFolder 目标文件夹
     * @param overwrite 是否覆盖已存在的文件
     * @return 复制是否成功
     */
    @JvmStatic
    fun copyFileToFolder(sourceFile: File, targetFolder: File, overwrite: Boolean = false): Boolean {
        // 检查源文件是否存在且为文件
        if (!sourceFile.exists() || !sourceFile.isFile) {
            return false
        }

        // 创建目标文件夹（如果不存在）
        if (!targetFolder.exists() && !targetFolder.mkdirs()) {
            return false
        }

        // 目标文件路径
        val targetFile = File(targetFolder, sourceFile.name)
        // 检查目标文件是否已存在
        if (targetFile.exists()) {
            if (!overwrite) {
                // 不覆盖，直接返回失败
                return false
            } else {
                // 覆盖，先删除目标文件
                if (!targetFile.delete()) {
                    return false
                }
            }
        }

        // 执行文件复制
        return try {
            val inputStream = FileInputStream(sourceFile)
            val outputStream = FileOutputStream(targetFile)

            // 使用缓冲流提高复制效率
            val buffer = ByteArray(1024 * 8) // 8KB缓冲区
            var bytesRead: Int

            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                outputStream.write(buffer, 0, bytesRead)
            }

            // 确保数据完全写入
            outputStream.flush()

            // 关闭流
            inputStream.close()
            outputStream.close()

            true
        } catch (e: IOException) {
            e.printStackTrace()
            Log.e("YDSimon", "复制单个文件到目标文件夹-IOException: ${e.message}")
            false
        } catch (e: SecurityException) {
            e.printStackTrace()
            Log.e("YDSimon", "复制单个文件到目标文件夹-SecurityException: ${e.message}")
            false
        }
    }

    /**
     * 复制文件夹到目标目录（包括所有子文件和子文件夹）
     * @param sourceFolder 源文件夹
     * @param targetParentFolder 目标父文件夹（源文件夹将被复制到该目录下）
     * @param overwrite 是否覆盖已存在的文件
     * @return 复制是否成功
     */
    @JvmStatic
    fun copyFolderToFolder(sourceFolder: File, targetParentFolder: File, overwrite: Boolean = false): Boolean {
        // 检查源文件夹是否存在且为目录
        if (!sourceFolder.exists() || !sourceFolder.isDirectory) {
            return false
        }

        // 创建目标文件夹（源文件夹将被复制到目标父文件夹下，保持同名）
        val targetFolder = File(targetParentFolder, sourceFolder.name)
        if (!targetFolder.exists() && !targetFolder.mkdirs()) {
            return false
        }

        // 获取源文件夹下的所有文件和子文件夹
        val files = sourceFolder.listFiles() ?: return true
        files.forEach { file ->
            if (file.isDirectory) {
                // 递归复制子文件夹
                if (!copyFolderToFolder(file, targetFolder, overwrite)) {
                    return false
                }
            } else {
                // 复制文件
                if (!copyFileToFolder(file, targetFolder, overwrite)) {
                    return false
                }
            }
        }

        return true
    }

    /**
     * 复制文件夹到目标目录（包括所有子文件和子文件夹）
     * @param sourceFolder 源文件夹
     * @param targetFolder 目标文件夹
     * @param overwrite 是否覆盖已存在的文件
     * @return 复制是否成功
     */
    @JvmStatic
    fun copyFolderChildToFolder(sourceFolder: File, targetFolder: File, overwrite: Boolean = false): Boolean {
        // 检查源文件夹是否存在且为目录
        if (!sourceFolder.exists() || !sourceFolder.isDirectory) {
            return false
        }

        // 确保目标文件夹存在
        if (!targetFolder.exists() && !targetFolder.mkdirs()) {
            return false
        }

        // 获取源文件夹下的所有文件和子文件夹
        val files = sourceFolder.listFiles() ?: return true
        files.forEach { file ->
            if (file.isDirectory) {
                // 递归复制子文件夹
                if (!copyFolderToFolder(file, targetFolder, overwrite)) {
                    return false
                }
            } else {
                // 复制文件
                if (!copyFileToFolder(file, targetFolder, overwrite)) {
                    return false
                }
            }
        }

        return true
    }

    /**
     * 向SD卡中的文件写入字符串内容
     * @param content 要写入的字符串内容
     * @param targetFile 目标文件（例如：File(/sdcard/Documents/note.txt)）
     * @param append 是否追加内容（true: 追加到文件末尾，false: 覆盖原有内容）
     * @return 写入是否成功
     */
    @JvmStatic
    fun writeTextToSDFile(content: String, targetFile: File, append: Boolean = true): Boolean {
        // 检查SD卡是否可用
        if (!isSDCardAvailable()) {
            return false
        }

        var writer: BufferedWriter? = null
        return try {
            // 创建父目录（如果不存在）
            val parentDir = targetFile.parentFile
            if (parentDir != null && !parentDir.exists()) {
                if (!parentDir.mkdirs()) {
                    return false
                }
            }

            // 创建文件输出流（append参数控制是否追加）
            val fileOutputStream = FileOutputStream(targetFile, append)
            val outputStreamWriter = OutputStreamWriter(fileOutputStream, "UTF-8")
            writer = BufferedWriter(outputStreamWriter)

            // 写入内容
            writer.write(content + "\n")
            writer.flush()
            true
        } catch (e: IOException) {
            e.printStackTrace()
            Log.e("YDSimon", "向SD卡中的文件写入字符串内容-IOException: ${e.message}")
            false
        } catch (e: SecurityException) {
            Log.e("YDSimon", "向SD卡中的文件写入字符串内容-SecurityException: ${e.message}")
            e.printStackTrace()
            false
        } finally {
            // 确保流被关闭
            try {
                writer?.close()
            } catch (e: IOException) {
                Log.e("YDSimon", "向SD卡中的文件写入字符串内容-确保流被关闭-IOException: ${e.message}")
                e.printStackTrace()
            }
        }
    }

    /**
     * 从SD卡指定文件读取字符串内容
     * @param targetFile 目标文件（例如：File(/sdcard/Documents/note.txt)）
     * @return 读取到的字符串内容，读取失败返回null
     */
    @JvmStatic
    fun readTextFromSDFile(targetFile: File): String? {
        // 检查SD卡是否可读取
        if (!isSDCardAvailable()) {
            return null
        }

        // 检查文件是否存在且是文件
        if (!targetFile.exists() || !targetFile.isFile) {
            return null
        }

        var reader: BufferedReader? = null
        val stringBuilder = StringBuilder()

        return try {
            // 创建文件输入流，指定UTF-8编码
            val fileInputStream = FileInputStream(targetFile)
            val inputStreamReader = InputStreamReader(fileInputStream, "UTF-8")
            reader = BufferedReader(inputStreamReader)

            var line: String?
            // 逐行读取内容
            while (reader.readLine().also { line = it } != null) {
                stringBuilder.append(line)
                stringBuilder.append("\n") // 保留换行符
            }

            // 移除最后多余的换行符
            if (stringBuilder.isNotEmpty()) {
                stringBuilder.deleteCharAt(stringBuilder.length - 1)
            }

            stringBuilder.toString()
        } catch (e: IOException) {
            e.printStackTrace()
            Log.e("YDSimon", "从SD卡指定文件读取字符串内容-IOException: ${e.message}")
            null
        } catch (e: SecurityException) {
            e.printStackTrace()
            Log.e("YDSimon", "从SD卡指定文件读取字符串内容-SecurityException: ${e.message}")
            null
        } finally {
            // 确保流被关闭
            try {
                reader?.close()
            } catch (e: IOException) {
                e.printStackTrace()
                Log.e("YDSimon", "从SD卡指定文件读取字符串内容-确保流被关闭-IOException: ${e.message}")
            }
        }
    }

    /**
     * 从SD卡文件中删除指定字符串
     * @param targetStr 要删除的目标字符串
     * @param targetFile 目标文件（例如：File(/sdcard/Documents/note.txt)）
     * @param caseSensitive 是否区分大小写（默认区分）
     * @return 操作是否成功
     */
    @JvmStatic
    fun removeTextFromFile(targetStr: String, targetFile: File, caseSensitive: Boolean = true): Boolean {
        // 1. 先读取文件内容
        val fileContent = readTextFromSDFile(targetFile) ?: return false // 读取失败直接返回

        // 2. 检查内容中是否包含目标字符串
        if (!fileContent.contains(targetStr, ignoreCase = !caseSensitive)) {
            return true // 不包含目标字符串，视为操作成功
        }

        // 3. 移除目标字符串
        val newContent = if (caseSensitive) {
            fileContent.replace(targetStr, "")
        } else {
            // 不区分大小写替换（使用正则表达式）
            fileContent.replace(Regex(Regex.escape(targetStr), RegexOption.IGNORE_CASE), "")
        }

        // 4. 将处理后的内容写回文件（覆盖原有内容）
        return writeTextToSDFile(newContent, targetFile, false)
    }


}